home *** CD-ROM | disk | FTP | other *** search
/ AppleScript - The Beta Release / AppleScript - The Beta Release.iso / Documentation / develop / Apple Event Objects and You / Apple Event Objects (code) / cApplication.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-08  |  9.5 KB  |  312 lines  |  [TEXT/KAHL]

  1.  
  2.  
  3. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  4. /*                                                                                   */
  5. /*    This file contains the code for implementing the cApplication AE object.        */
  6. /*                                                                                   */
  7. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  8.  
  9. #include "AEPackObject.h"
  10. #include <Scrap.h>
  11. #include "AEObjects.h"
  12. #include "AERegistry.h"
  13.  
  14. #include "ScriptScrap.h"
  15. #include "Prototypes.h"
  16.  
  17.  
  18. /* Property from object accessors */
  19. pascal OSErr PropertyFromNullAccessor ( DescType desiredClass,
  20.             const AEDesc *container, DescType containerClass, DescType keyForm,
  21.             const AEDesc *keyData, AEDesc *returnedToken, long refCon )
  22. {
  23.     OSErr        err = noErr;
  24.     ourToken    tokenBody;
  25.     DescType    requestedProperty;
  26.     
  27.     /* In our model, all a property accessor does is copy the container */
  28.     /* token and change the token to represent a property. The token    */
  29.     /* handlers will do the actual reading and writing of the data in    */
  30.     /* the token.                                                        */
  31.     if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType))
  32.         return errAECantSupplyType;
  33.  
  34.     if (container->descriptorType != 'null')
  35.         return errAETypeError;
  36.  
  37.     requestedProperty = **(DescType**)keyData->dataHandle;
  38.     
  39.     /* Initialize the body of the token */
  40.     tokenBody.dispatchClass = cApplication;        /*  The parent of this object… */
  41.     tokenBody.flags            = kPropToken;        /*  We're returning a property code */
  42.     tokenBody.docWindow        = NULL;                /*  Not used */
  43.     tokenBody.fRefNum        = 0;                /*  Not used */
  44.  
  45.     /* Check to see if this is a legal property code for this object class */
  46.     switch (requestedProperty) {
  47.         case pBestType:
  48.         case pClass:
  49.         case pDefaultType:
  50.         case pInsertionLoc:
  51.         case pIsFrontProcess:
  52.         case pName:
  53.         case pUserSelection:
  54.         case pVersion:
  55.             tokenBody.propertyCode    = requestedProperty;
  56.         break;
  57.  
  58.         case pClipboard:
  59.             tokenBody.propertyCode    = requestedProperty;
  60.             tokenBody.flags            = kPropToken;
  61.         break;
  62.                 
  63.         default:
  64.             return errAECantSupplyType;
  65.     }
  66.     
  67.     /* Pass this token back to the OSL */
  68.     return AECreateDesc(desiredClass, (Ptr)&tokenBody, sizeof(tokenBody), returnedToken);
  69. } /* PropertyFromNullAccessor */
  70.  
  71.  
  72. /* Token resolvers -- read, write */
  73.  
  74. OSErr App_ReadTokenData(const AEDesc *theToken, AEDesc *tokenContents)
  75. {
  76.     long        versionCode = 0x0002;
  77.     DescType    scratchType;
  78.     DescType    propCode;
  79.     OSErr        err            = noErr;
  80.     AEDesc        keyData,
  81.                 nullDesc    = {'null', NULL};
  82.     AEDesc        scratchDesc;
  83.     long        documentNumber;
  84.         
  85.     if (tokenFlags(*theToken) & kPropToken) {
  86.         /* Return any readable properties of the appointment */
  87.         propCode = tokenPropCode(*theToken);
  88.         switch (propCode) {
  89.             case pBestType:
  90.             case pClass: 
  91.                 scratchType = cApplication;
  92.                 return AECreateDesc(typeType, (Ptr)&scratchType, sizeof(scratchType), tokenContents);
  93.             break;
  94.  
  95.             case pDefaultType:
  96.                 scratchType = cApplication;
  97.                 return AECreateDesc(typeType, (Ptr)&scratchType, sizeof(scratchType), tokenContents);
  98.             break;
  99.  
  100.             case pInsertionLoc:
  101.                 if (FrontWindow() != NULL) {
  102.                     /*  return the object specifier "window 1" */
  103.                     documentNumber = 1;
  104.                     (void)AECreateDesc(typeIndexDescriptor, (Ptr)&documentNumber, sizeof(documentNumber), &keyData);
  105.                     (void)CreateObjSpecifier(cDocument, &nullDesc, formAbsolutePosition, &keyData, true, tokenContents);
  106.                     AEDisposeDesc(&keyData);
  107.                 } else
  108.                     *tokenContents = nullDesc;
  109.             break;
  110.             
  111.             case pIsFrontProcess:
  112.                 return AECreateDesc(cBoolean, (Ptr)&gInFront, sizeof(gInFront), tokenContents);
  113.             break;
  114.             
  115.             case pName: {
  116.                 Str255    appName;
  117.                 short    refNum;
  118.                 Handle    h, textHandle;
  119.                 
  120.                 GetAppParms(appName, &refNum, &h);
  121.                 PstringToText((char *)appName, &textHandle);
  122.                 tokenContents->descriptorType = typeChar;
  123.                 tokenContents->dataHandle = textHandle;
  124.             } break;
  125.             
  126.             
  127.             case pVersion:
  128.                 return AECreateDesc(cLongInteger, (Ptr)&versionCode, sizeof(long), tokenContents);
  129.             break;
  130.  
  131.             case pClipboard: {
  132.                 /*  Return all of the items currently on the clipboard */
  133.                 /*  The returned information is an AEList, and each data type */
  134.                 /*  on the scrap gets its own entry in the list */
  135.                 /*  Alas, since the OS doesn't supply the tools for getting all */
  136.                 /*  of the types in the scrap, we have to scan the scrap ourselves... */
  137.                 char        *scrapPtr, *scrapEnd;
  138.                 PScrapStuff    scrapInfo;
  139.                 long        scrapSize;
  140.                 OSType        itemType;
  141.                 long        itemLength;
  142.                 long        index;
  143.                 
  144.                 err = AECreateList(NULL, 0, false, tokenContents);
  145.                 if (err != noErr) break;
  146.                 
  147.                 err = LoadScrap();                /*  Make sure the scrap is in memory */
  148.                 if (err != noErr) break;
  149.                 
  150.                 scrapInfo = InfoScrap();        /*  Get the base address of the scrap in RAM */
  151.                 MoveHHi(scrapInfo->scrapHandle);
  152.                 HLock  (scrapInfo->scrapHandle);/* ...and lock it */
  153.                 scrapPtr = (char *)*scrapInfo->scrapHandle;
  154.                 scrapEnd = scrapPtr + scrapInfo->scrapSize;
  155.                 
  156.                 /*  Now, we can proceed to scan the scrap in memory and extract each type */
  157.                 index = 1;
  158.                 while (scrapPtr < scrapEnd) {
  159.                     itemType = *(OSType *)scrapPtr;
  160.                     scrapPtr += sizeof(itemType);
  161.                     itemLength = *(long *)scrapPtr;
  162.                     scrapPtr += sizeof(itemLength);
  163.                     /*  Move this information into the next entry on the list */
  164.                     err = AEPutPtr(tokenContents, index, itemType, scrapPtr, itemLength);
  165.                     if (err != noErr) return err;
  166.                     index++;
  167.                     /*  Bump the pointer to the start of the next item */
  168.                     if (itemLength & 1) itemLength++; /*  If it's odd, make it even */
  169.                     scrapPtr += itemLength;
  170.                 }
  171.                 HUnlock  (scrapInfo->scrapHandle);
  172.             } break;
  173.         }
  174.     }
  175.     else
  176.         /*  We should return an ospec for the application here */
  177.         err = errAENoSuchObject;
  178.  
  179.     return err;
  180. } /* App_ReadTokenData */
  181.  
  182.  
  183. OSErr App_WriteTokenData(const AEDesc *theToken, const AEDesc *data)
  184. {
  185.     OSErr        err            = noErr;
  186.     long        numItems, index;
  187.     AEDesc        currItemDesc = {'null', NULL};
  188.     AEKeyword     theAEKeyword;
  189.     
  190.     if ((tokenFlags(*theToken) & kPropToken) && (tokenPropCode(*theToken) == pClipboard)) {
  191.         /* Only the clipboard property is writable */
  192.         
  193.         /*  The data should be an AE list containing a series of things to be placed on the */
  194.         /*  clipboard. The data type of each item is also the clipboard type for that data */
  195.         /*  Note that App_SetData has extracted the information as a list for us */
  196.         err = ZeroScrap();
  197.         if (err != noErr) return err;
  198.         
  199.         (void)AECountItems(data, &numItems);
  200.         for (index = 1; index <= numItems; index++) {
  201.             /*  Copy each item onto the clipboard */
  202.             err = AEGetNthDesc(data, index, typeWildCard, &theAEKeyword, &currItemDesc);
  203.             if (err != noErr) {
  204.                 if (currItemDesc.dataHandle != NULL) AEDisposeDesc(&currItemDesc);
  205.                 return err;
  206.             }
  207.             HLock(currItemDesc.dataHandle);
  208.             err = PutScrap(GetHandleSize(currItemDesc.dataHandle), currItemDesc.descriptorType,
  209.                            *currItemDesc.dataHandle);
  210.             AEDisposeDesc(&currItemDesc);
  211.             currItemDesc.dataHandle = NULL;
  212.         }
  213.     }
  214.     else
  215.         err = errAENotModifiable;
  216.  
  217.     return err;
  218. } /* App_WriteTokenData */
  219.  
  220.  
  221. /* Individual event handlers */
  222. OSErr App_GetData(AppleEvent *message, AppleEvent *reply, long refcon,
  223.                 AEDesc *token, AEDesc *replyObject)
  224. {        
  225.     return App_ReadTokenData(token, replyObject);
  226. } /* App_GetData */
  227.  
  228.  
  229. OSErr App_SetData(AppleEvent *message, AppleEvent *reply, long refcon,
  230.                 AEDesc *token, AEDesc *replyObject)
  231. {
  232.     AEDesc    theData;
  233.     OSErr    err;
  234.  
  235.     /*  Since only the "pClipboard" property is writable, and the data for that is */
  236.     /*  supposed to be in a list, we'll extract the data as a list */
  237.     err = AEGetKeyDesc(message, keyAEData, typeAEList, &theData);
  238.     if (err == noErr) {
  239.         err = App_WriteTokenData(token, &theData);
  240.         (void)AEDisposeDesc(&theData);
  241.     }
  242.     return err;
  243. } /* App_SetData */
  244.  
  245.  
  246. /* Object command dispatcher */
  247.  
  248. OSErr App_AE_Dispatcher(const AppleEvent *message, AppleEvent *reply, long refCon,
  249.                         AEEventClass classID, AEEventID eventID,
  250.                         const AEDesc *ospec, const AEDesc *token)
  251. {
  252.     OSErr    err = noErr;
  253.     AEDesc    replyDesc = {'null', 0L};
  254.  
  255.     if (classID == kAECoreSuite) {
  256.         switch (eventID) {
  257.  
  258.             /*  This code is assuming that the object specifier resolves to a single item. */
  259.             /*  This isn't always true… */
  260.             case kAEGetData:
  261.                 err = App_GetData(message, reply, refCon, token, &replyDesc);
  262.             break;
  263.  
  264.             case kAEGetDataSize: {
  265.                 /*  We'll do this one by executing "Get Data" and then returning the  */
  266.                 /*  size of the information. This is not necesarily the most efficient */
  267.                 /*  way to do things if your returned data is large. */
  268.                 
  269.                 AEDesc    tempDesc = {'null', NULL};
  270.                 long    dataSize;
  271.                 
  272.                 err = App_GetData(message, reply, refCon, token, &tempDesc);
  273.                 if (tempDesc.dataHandle != NULL) {
  274.                     dataSize = GetHandleSize(tempDesc.dataHandle);
  275.                     (void)AECreateDesc(typeLongInteger, (Ptr)&dataSize, sizeof(dataSize), &replyDesc);
  276.                     (void)AEDisposeDesc(&tempDesc);
  277.                 }
  278.             }
  279.             break;
  280.  
  281.             case kAESetData:
  282.                 err = App_SetData(message, reply, refCon, token, &replyDesc);
  283.             break;
  284.  
  285.             /* Events which we don't handle */
  286.             case kAEClone:
  287.             case kAEClose:
  288.             case kAECountElements:
  289.             case kAECreateElement:    /*  Handled by the element itself */
  290.             case kAEDelete:
  291.             case kAEDoObjectsExist:
  292.             case kAEGetClassInfo:
  293.             case kAEMove:
  294.             case kAEOpen:
  295.             default:
  296.                 err = errAEEventNotHandled ;
  297.         }
  298.     }
  299.     else
  300.         err = errAEEventNotHandled;
  301.  
  302.     /* See if we need to return anything */
  303.     if ((err == noErr) && (replyDesc.descriptorType != 'null')
  304.             && (reply->descriptorType != 'null')) {    /* Note: if the other side didn't ask for a reply, this could be a null desc */
  305.             /*  This code should be modified to handle lists */
  306.             err = AEPutParamDesc(reply, keyDirectObject, &replyDesc);
  307.             (void)AEDisposeDesc(&replyDesc);
  308.     }
  309.  
  310.     return err;
  311. } /* App_Dispatcher */
  312.